package com.hibase.core.oss.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.CopyObjectRequest;
import com.aliyun.oss.model.CopyObjectResult;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectResult;
import com.hibase.common.exception.HibaseException;
import com.hibase.core.oss.config.OssProperties;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.log4j.Log4j2;

/**
 * @Description: TODO
 * @Author: liuyunlei
 * @Date: 2020/10/20 10:47
 * @Version: 1.0
 */
@Log4j2
@Component
public class AliyunOSSUtil {

	@Autowired
	private OssProperties ossProperties;
	
	private static AliyunOSSUtil aliyunOSSUtil;
	
	@PostConstruct // 通过@PostConstruct实现初始化bean之前进行的操作
	public void init() {
		aliyunOSSUtil = this;
		aliyunOSSUtil.ossProperties = this.ossProperties;
		// 初使化时将已静态化的testService实例化
	}

	private static final String TAG = "AliyunOSSUtil";

	public static final String BASE_SAVE_PATH = "filesystem".concat(StrUtil.SLASH)
			.concat("Files".concat(StrUtil.SLASH).concat("EFiles").concat(StrUtil.SLASH));

	/**
	 * 逻辑删除文件
	 *
	 * @param sourceBucketName
	 * @param sourceObjectName
	 * @return delVersionId
	 */
	public static String delFileObj(String sourceBucketName, String sourceObjectName) {
		return transferOSSFile(sourceBucketName, sourceObjectName, true, aliyunOSSUtil.ossProperties.getDelBucket(), sourceObjectName);
	}

	/**
	 * 将文件从临时区转移到正式区
	 *
	 * @param sourceBucketName
	 * @param sourceObjectName
	 * @param sourceVersionId
	 * @return
	 */
	public static String saveFileObj(String sourceBucketName, String sourceObjectName, String sourceVersionId) {
		return transferOSSFile(sourceBucketName, sourceObjectName, true, aliyunOSSUtil.ossProperties.getFormalBucket(), sourceObjectName);
	}

	/**
	 * 上传文件流
	 * @param bucketName    存储空间名
	 * @param objectName    文件对象名
	 * @param inputStream 文件流
	 * @return versionId
	 */
	public static String uploadFileStream(String bucketName, String objectName, InputStream inputStream) {
		OSS ossClient = new OSSClientBuilder()
				.build(aliyunOSSUtil.ossProperties.getEndpoint(),
						aliyunOSSUtil.ossProperties.getAccessKeyId(),
						aliyunOSSUtil.ossProperties.getAccessKeySecret());
		try {
			PutObjectResult result = ossClient.putObject(bucketName, objectName, inputStream);
			String versionId = result.getETag();
			if (StrUtil.isNotBlank(versionId)) {
				return versionId;
			}
			return null;
		} catch (Exception e) {
			e.printStackTrace();
			throw new HibaseException(e);
		} finally {
			if (ObjectUtil.isNotEmpty(ossClient)) {
				ossClient.shutdown();
			}
		}
	}

	/**
	 * 上传文件流
	 *
	 * @param bucketName    存储空间名
	 * @param objectName    文件对象名
	 * @param multipartFile 文件流
	 * @return versionId
	 */
	public static String uploadFileStream(String bucketName, String objectName, MultipartFile multipartFile) {
		try {
			return uploadFileStream(bucketName,objectName,multipartFile.getInputStream());
		} catch (IOException e) {
			e.printStackTrace();
			throw new HibaseException(e);
		}
	}

	/**
	 * OSS迁移文件
	 *
	 * @param sourceBucketName      来源存储空间
	 * @param sourceObjectName      来源对象名
	 * @param sourceObjectName      来源对象版本号
	 * @param destinationBucketName 目的存储空间
	 * @param destinationObjectName 目的对象名
	 * @return versionId
	 */
	public static String transferOSSFile(String sourceBucketName, String sourceObjectName, boolean sourceDel,
			String destinationBucketName, String destinationObjectName) {

		OSS ossClient = new OSSClientBuilder().build(aliyunOSSUtil.ossProperties.getEndpoint(), aliyunOSSUtil.ossProperties.getAccessKeyId(),
				aliyunOSSUtil.ossProperties.getAccessKeySecret());

		try {

			CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceObjectName,
					destinationBucketName, destinationObjectName);

			CopyObjectResult copyObjectResult = ossClient.copyObject(copyObjectRequest);

			// 是否要删除 源文件
			if (sourceDel) {

				// 删除指定版本的Object。
				ossClient.deleteObject(sourceBucketName, sourceObjectName);

			}

			return copyObjectResult.getETag();

		} catch (Exception e) {

			log.error(TAG, "移动文件发生异常：{}", e.getMessage());

			return "error";

		} finally {

			ossClient.shutdown();

		}

	}

	/**
	 * 获取OSS对象文件流
	 *
	 * @param bucketName
	 * @param ObjectName
	 * @return
	 */
	public static InputStream downloadFileOssObjStream(String bucketName, String ObjectName) {

		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(aliyunOSSUtil.ossProperties.getEndpoint(), aliyunOSSUtil.ossProperties.getAccessKeyId(),
				aliyunOSSUtil.ossProperties.getAccessKeySecret());

		// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
		OSSObject ossObject = ossClient.getObject(bucketName, ObjectName);

		return ossObject.getObjectContent();
	}

	/**
	 * 根据文件路径上传本地文件 key:为存储路径+文件名+文件后缀
	 *
	 * @param filePath
	 */
	public static void uploadLocalFile(String bucketName, String filePath, String ObjectName) {
		OSS ossClient = new OSSClientBuilder().build(aliyunOSSUtil.ossProperties.getEndpoint(), aliyunOSSUtil.ossProperties.getAccessKeyId(),
				aliyunOSSUtil.ossProperties.getAccessKeySecret());
		PutObjectResult result = ossClient.putObject(bucketName, ObjectName, new File(filePath));
		String ETag = result.getETag();
		log.info("A：" + ETag);
		log.info("changdu：" + ETag.length());
		log.info("versionId：" + result.getVersionId());

		ossClient.shutdown();
	}

	public static void main(String[] s) {

		String file = "filesystem\\SZFiles\\EFiles\\default\\20201107\\20201107hibase_abe6279b02634be0864b3b0f3228ac9a.xlsx";

		uploadLocalFile(aliyunOSSUtil.ossProperties.getTempBucket(), "C:\\Users\\TimBrian\\Pictures\\Camera Roll\\2.png", "test");

//        transferOSSFile(TempBucket,file,true,FormalBucket,file);

		try {

//            FileInputStream fileInputStream=new FileInputStream("C:\\666.jpg");
//
//            log.info(fileInputStream.available());

			InputStream in = downloadFileOssObjStream(aliyunOSSUtil.ossProperties.getFormalBucket(), file);

			// FileInputStream f = (FileInputStream) in;

			log.info(in.available());

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}
